import basebackend
import pycassa
import pycassa.index
import uuid
import datetime
from fields import *

class CassaBackend(basebackend.BaseBackend):
    OPS = {
        "=": pycassa.index.EQ,
        "<": pycassa.index.LT,
        ">": pycassa.index.GT,
        "<=": pycassa.index.LTE,
        ">=": pycassa.index.GTE,
    }
    
    MAX_ROW_COUNT = 10000000
    
    def __init__(self, config):
        basebackend.BaseBackend.__init__(self, config, "_id")

    def _getDict(self, document):
        resultdict = {}
        for field in document.getFields():
            resultdict[field] = self._toString(getattr(document, field))
        for (docname, attrname), field in document.getForeignFields().items():
            resultdict[docname + "_" + attrname] = str(field.get_value())
        return resultdict

    def _buildDict(self, document):
        resultdict = self._getDict(document)
        #for reference in document.getReferences():
        #    resultdict[reference] = self._buildDict(
        #        getattr(document, reference))
        # ha lazy a referencia, es meg nem toltodott be, nem kell vele foglalkozni
        return resultdict

    def _getColFam(self, documentcls):
        return pycassa.ColumnFamily(self.pool, documentcls.getName())

    def connect(self):
        self.pool = pycassa.connect(self._config.db_settings['db'],
                                    ["%s:%s" % (self._config.db_settings['host'],
                                                self._config.db_settings['port'])])

    def disconnect(self):
        pass
        
    def getByKey(self, documentcls, key):
        col_fam = self._getColFam(documentcls)
        resultdict = col_fam.get(key)
        resultobj = documentcls(**resultdict)
        resultobj.setKey(key)
        resultobj.setDirty(False)
        resultobj.setNew(False)

        return resultobj

    def get(self, documentcls, criterias):
        # < > like and or distinct
        #attribute_list, criterias, limit, order
        # cassandraval nem megvalosithato az or, programozottan kell
        # cassandraval nincs like, csak szoeleji egyezes a keyre
        spec = {}
        col_fam = self._getColFam(documentcls)

        if len(criterias) == 0:
            resultdicts = col_fam.get_range()
        else:
            expr_list = []
            for crit in criterias:
                expr = pycassa.index.create_index_expression(crit.field, self._toString(crit.value),
                                                             self.OPS[crit.operator])
                expr_list.append(expr)
            clause = pycassa.index.create_index_clause(expr_list, count=self.MAX_ROW_COUNT)
        
            resultdicts = col_fam.get_indexed_slices(clause)
    
        resultobjs = []
        for resultdict in resultdicts:
            key = resultdict[0]
            initdict = {}
            for fieldname, fieldtype in documentcls.getFieldTypes().items():
                if resultdict[1].has_key(fieldname):
                    initdict[fieldname] = \
                        self._convertValue(fieldtype, resultdict[1][fieldname])
            for refname in documentcls.getReferenceTypes():
                if resultdict[1].has_key(refname):
                    initdict[refname] = resultdict[1][refname]
            resultobj = documentcls(**initdict)
            resultobj.setKey(key)
            resultobj.setDirty(False)
            resultobj.setNew(False)
            resultobjs.append(resultobj)
            
        return resultobjs
    
    def _convertValue(self, fieldtype, value):
        if value == None:
            return None
            
        t = fieldtype
        if t == StringField:
            return value
        elif t == IntegerField:
            return int(value)
        elif t == DateField:
            return datetime.datetime.strptime(value, "%Y-%m-%d %H:%M:%S.%f")
        elif t == BoolField:
            return value == 'True'
        
        return None
        
    def _toString(self, value):
        if type(value) == datetime.datetime:
            return value.strftime("%Y-%m-%d %H:%M:%S.%f")
        else:
            return str(value)
        
    def _save(self, document, insert):
        savedict = self._buildDict(document)
        col_fam = self._getColFam(document)
        if insert:
            key = str(uuid.uuid1())
        else:
            key = document.getKey()
        col_fam.insert(key, savedict)
        return key

    def insert(self, document):
        return self._save(document, True)

    def update(self, document):
        return self._save(document, False)

    def delete(self, document):
        if document.isNew():
            return
        collection = self._getCollection(document)
        collection.remove(document.getKey())
